<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>this指向问题2(改变)</title>
  </head>
  <body>
    <script>
      // 关于改变this指向问题，javaScript 为我们专门提供了一些函数方法来帮我们更优雅的处理函数内部 this 的指向问题，
      // 常用的有 bind()、call()、apply() 三种方法.
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // 1.call 方法
      // fun.call(thisArg, arg1, arg2, ...) call的作用就是把fun的方法放到thisArg上使用，后面的argument1..这些做为参数传入。

      // function add(x, y) {
      //   console.log(x + y)
      // }
      // function minus(x, y) {
      //   console.log(x - y)
      // }
      // add.call(minus, 1, 1) //2
      // 这个例子中的意思就是用 add 来替换 minus ，add.call(minus ,1,1) == add(1,1) ，所以运行结果为：console.log (2); // 注意：js 中的函数其实是对象，函数名是对 Function 对象的引用。

      // var o = {
      //   name: 'andy',
      // }
      // function fn(a, b) {
      //   console.log(this.name)
      //   console.log(a + b)
      // }
      // fn.call(o, 1, 2)
      // call 第一个可以调用函数 第二个可以改变函数内的this 指向

      // call 的主要作用可以实现继承
      // function myfunc1() {
      //   this.name = 'Lee'
      //   this.myTxt = function (txt) {
      //     console.log('i am', txt)
      //   }
      // }

      // function myfunc2() {
      //   console.log(this, '我是fun2的this')
      //   myfunc1.call(this)
      // }

      // var myfunc3 = new myfunc2()
      // myfunc3.myTxt('Geing') // i am Geing
      // console.log(myfunc3.name) // Lee
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************

      // 2.apply 方法  (cal和apply是直接调用函数 ,除了参数不同 其它基本一致)
      // fun.apply(thisArg, [param1,param2,...]) =>函数名.apply(目标对象,[参数1,参数2,...参数n])

      // function arrayMax(array) {
      //   // 使用allay将Math.max挂载在null上执行数组，因为apply是传入一个数组参数的的
      //   return Math.max.apply(null, array)
      // }
      // console.log(arrayMax([1, 2, 3, 4]))

      // function arrayConcat(array1, array2) {
      //   // 合并数组
      //   Array.prototype.push.apply(array1, array2)
      //   return array1
      // }
      // console.log(arrayConcat([1, 2, 3], [4, 5, 6]))
      // let cat = {
      //   name: '咪咪',
      //   miao: function () {
      //     console.log(`${this.name}会 喵喵`)
      //   },
      // }
      // let dog = {
      //   name: '叨哥',
      //   bark: function () {
      //     console.log(`${this.name}会 汪汪`)
      //   },
      //   compute: function (a, b) {
      //     console.log(`${this.name}算数`, a + b)
      //   },
      // }
      // //  猫猫想学狗叫
      // dog.bark.apply(cat) //通过改变this的指向 ，cat里面的this变成了dog的this，因此cat学会了dog的bark（汪汪叫）的技能
      // //  猫猫想学狗做算数（此时需要传参数 同call类似 apply需要传递数组参数）
      // dog.compute.apply(cat, [1, 9])
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      // ******************************************************************
      //  3.bind() 方法
      // fun.bind(thisArg, param1, param2, ...) call/apply改变了函数的this上下文后马上执行该函数  bind则是返回改变了上下文后的函数,不执行该函数
      // 返回值:
      // call/apply 返回fun的执行结果
      // bind返回fun的拷贝，并指定了fun的this指向，保存了fun的参数
      // var a = {
      //   name: 'Cherry',
      //   fn: function (a, b) {
      //     console.log(a + b)
      //   },
      // }

      // var b = a.fn
      // b.bind(a, 1, 2)()

      // function fun() {
      //   console.log(this.name, arguments)
      // }
      // let obj = {
      //   name: 'clying',
      // }
      // fun.prototype.age = 23
      // let b = fun.bind(obj, 3)
      // let instance = new b(4) // this指向new b
      // let instance = b(4) // this指向new obj

      // console.log(instance.age)

      // console.log(b.bind(a, 1, 2), ' b.bind(a, 1, 2)')
      // bind()方法创建一个新的函数, 当被调用时，将其this关键字设置为提供的值，在调用新函数时，在任何提供之前提供一个给定的参数序列。
      // 所以我们可以看出，bind 是创建一个新的函数，我们必须要手动去调用：
    </script>
  </body>
</html>
